//
// Created by xunx on 2018/12/9.
//

#include "Minesweeping.h"
#include "../Core/Resource.h"
#include <ctime>
#include "../Core/Sprite.h"
#include "../Core/Window.h"

Minesweeping::Minesweeping() {
    BoomNumble = 50;
    Load();
    Generate();
    inputtime = glfwGetTime();

}

Minesweeping::~Minesweeping() {
    for (int i = 0; i < 400; ++i) {
        Resource::DeleteSprite(std::to_string(i));
    }
}

void Minesweeping::Load() {
    Resource::LoadTexture2D("Resource/img/unknow.png", false, "unknow");
    Resource::LoadTexture2D("Resource/img/null.png", false, "null");
    Resource::LoadTexture2D("Resource/img/flag.png", false, "flag");
    Resource::LoadTexture2D("Resource/img/boom.png", false, "boom");
    for (int i = 1; i < 9; ++i) {
        Resource::LoadTexture2D(("Resource/img/" + std::to_string(i) + ".png").c_str(), false, std::to_string(i));
    }
}

void Minesweeping::Generate() {
    for (int i = 0; i < 400; ++i) {
        int x = i / 20;
        int y = i % 20;
        Resource::CreateSprite(std::to_string(i), 40.f, 30.f, 40 * x, 30 * y, 0.f, Resource::GetTexture2D("unknow"));
    }
    for (int i = 0; i < BoomNumble; ++i) {
        int x = i / 20;
        int y = i % 20;
        Booms[x][y] = true;
    }
    srand((int) time(0));
    for (int i = 399; i >= 0; i--) {
        int iX = i / 20;
        int iY = i % 20;
        int RandNumble = rand() % (i + 1);
        int RandX = RandNumble / 20;
        int RandY = RandNumble % 20;
        Swap(iX, iY, RandX, RandY);
    }
    InitNumbers();
}

void Minesweeping::Swap(int x1, int y1, int x2, int y2) {
    bool t = Booms[x1][y1];
    Booms[x1][y1] = Booms[x2][y2];
    Booms[x2][y2] = t;
}

void Minesweeping::InitNumbers() {
    for (int i = 0; i < 400; ++i) {
        int x = i / 20;
        int y = i % 20;
        if (Booms[x][y])
            Numbers[x][y] = -1; //雷区
        Numbers[x][y] = 0;
        for (int k = x - 1; k <= x + 1; ++k) {
            for (int l = y - 1; l <= y + 1; ++l) {
                if (isArea(k, l) && Booms[k][l])
                    Numbers[x][y]++;
            }
        }
    }
}


void Minesweeping::GameStart() {
    for (int i = 0; i < 400; ++i) {
        int x = i / 20;
        int y = i % 20;
        if (Open[x][y]) {
            if (Booms[x][y]) Resource::GetSprite(std::to_string(i))->SetTexture(Resource::GetTexture2D("boom"));
            else if (Numbers[x][y] > 0 && Numbers[x][y] < 9)
                Resource::GetSprite(std::to_string(i))->SetTexture(
                        Resource::GetTexture2D(std::to_string(Numbers[x][y])));
            else
                Resource::GetSprite(std::to_string(i))->SetTexture(Resource::GetTexture2D("null"));
        } else {
            if (Flag[x][y])
                Resource::GetSprite(std::to_string(i))->SetTexture(Resource::GetTexture2D("flag"));
            else
                Resource::GetSprite(std::to_string(i))->SetTexture(Resource::GetTexture2D("unknow"));
        }
    }


    if (Window::GetMousebuttonIsPress(GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS &&
        Window::GetMousebuttonIsPress(GLFW_MOUSE_BUTTON_LEFT) != GLFW_RELEASE &&
        Window::GetMousebuttonIsPress(GLFW_MOUSE_BUTTON_LEFT) != GLFW_REPEAT) {
        float currtime = glfwGetTime();
        if (currtime - inputtime > 0.1f) {
            int x = Window::GetMousePosition().x / 40.f;
            int y = Window::GetMousePosition().y / 30.f;
            if (!Open[x][y]) {
                Open[x][y] = true;
                if (Booms[x][y]) {
                    GameOver();
                } else {
                    OpenBlank(x, y);
                }
            }
        }
        inputtime = currtime;
    }
    if (Window::GetMousebuttonIsPress(GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS &&
        Window::GetMousebuttonIsPress(GLFW_MOUSE_BUTTON_RIGHT) != GLFW_RELEASE &&
        Window::GetMousebuttonIsPress(GLFW_MOUSE_BUTTON_RIGHT) != GLFW_REPEAT) {
        float currtime = glfwGetTime();
        if (currtime - inputtime > 0.1f) {
            int x = Window::GetMousePosition().x / 40.f;
            int y = Window::GetMousePosition().y / 30.f;
            if (!Open[x][y])Flag[x][y] = !Flag[x][y];
        }
        inputtime = currtime;
    }
}

bool Minesweeping::isArea(int x, int y) {
    return x >= 0 && y >= 0 && x < 20 && y < 20;
}

void Minesweeping::OpenBlank(int x, int y) {
    if (!isArea(x, y)) return;
    if (Booms[x][y]) return;
    Open[x][y] = true;
    if (Numbers[x][y] > 0) return;

    for (int i = x - 1; i <= x + 1; ++i) {
        for (int j = y - 1; j <= y + 1; ++j) {
            if (isArea(i, j) && !Booms[i][j] && !Open[i][j])
                OpenBlank(i, j);
        }
    }
}

void Minesweeping::GameOver() {
    for (int i = 0; i < 400; ++i) {
        int x = i / 20;
        int y = i % 20;
        Open[x][y] = false;
        Flag[x][y] = false;
    }
}



